/**
  ******************************************************************************
  * @file    :i2c.c
  * @author  :MG Team
  * @version :V1.0
  * @date
  * @brief
  ******************************************************************************
***/

/* Includes ------------------------------------------------------------------*/
#include "Includes.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

static uint8_t DevAddr = 0x6c << 1;

static void I2C_Start(void)
{
    SDA_OUT();

    SDA_SET();
    SCL_SET();

    SDA_CLR();
    SCL_CLR();
}

static void I2C_Stop(void)
{
    SDA_OUT();

    SDA_CLR();
    SCL_CLR();

    SCL_SET();
    SDA_SET();
}

static uint8_t I2C_Send_byte(uint8_t data)
{
    uint8_t i;

    for(i=0;i<8;i++)
    {
        if(data&0x80)
        {
            SDA_SET();
        }
        else
        {
            SDA_CLR();
        }
        data=data<<1;
        SCL_SET();
        SCL_CLR();
    }
    SDA_SET();

    SDA_IN();

    SCL_SET();

    i = SDA_READ();
    SCL_CLR();

    SDA_OUT();
    return i;
}

static uint8_t I2C_Receive_byte(uint8_t ack)
{
    uint8_t i,data=0;

    SDA_IN();

    for(i=0;i<8;i++)
    {
        SCL_SET();

        data <<= 1;
        if(SDA_READ())
        {
            data |= 1;
        }

        SCL_CLR();
    }

    SDA_OUT();

    if (ack)
    {
        SDA_CLR();
    }
    else
    {
        SDA_SET();
    }

    SCL_SET();
    __asm("nop");
    __asm("nop");
    SCL_CLR();

    return data;
}


/*******************************************************************************
* Function   :     	I2C_Write_Buffer
* Parameter  :     	uint8_t reg, uint8_t *dataBuf, uint8_t len
* Returns    :     	void
* Description:
* Note:      :
*******************************************************************************/
void I2C_Write_Buffer(uint8_t reg, uint8_t *dataBuf, uint8_t len)
{
    uint8_t noack,temp0;

    I2C_Start();

    noack = I2C_Send_byte(DevAddr);
    if (noack)
    {
        I2C_Stop();
        return;
    }

    noack = I2C_Send_byte(reg);
    if (noack)
    {
        I2C_Stop();
        return;
    }

    for(temp0=0;temp0<len;temp0++)
    {
        noack = I2C_Send_byte(*dataBuf);
        if (noack)
        {
            I2C_Stop();
            return;
        }
        dataBuf++;
    }
    I2C_Stop();
}

/*******************************************************************************
* Function   :     	I2C_Read_Buffer
* Parameter  :     	uint8_t reg, uint8_t *dataBuf, uint8_t len
* Returns    :
* Description:
* Note:      :
*******************************************************************************/
void I2C_Read_Buffer(uint8_t reg, uint8_t *dataBuf, uint8_t len)
{
    uint8_t noack,temp0;

    I2C_Start();

    noack = I2C_Send_byte(DevAddr);
    if (noack)
    {
        I2C_Stop();
        return;
    }

    noack = I2C_Send_byte(reg);
    if (noack)
    {
        I2C_Stop();
        return;
    }

    I2C_Start();

    noack = I2C_Send_byte(DevAddr | 0x01);
    if (noack)
    {
        I2C_Stop();
        return;
    }

    for(temp0=0;temp0<len;temp0++)
    {
        if (temp0 == (len - 1))
        {
            *(dataBuf+temp0) = I2C_Receive_byte(0);
        }
        else
        {
            *(dataBuf+temp0) = I2C_Receive_byte(1);
        }
    }
    I2C_Stop();
}


/*******************************************************************************
* Function   :     	I2C_Write_Reg
* Parameter  :     	uint8_t reg, uint8_t data
* Returns    :     	void
* Description:
* Note:      :
*******************************************************************************/
void I2C_Write_Reg(uint8_t reg, uint8_t data)
{
    I2C_Write_Buffer(reg,&data,1);
}

/*******************************************************************************
* Function   :     	I2C_Read_Reg
* Parameter  :     	uint8_t reg
* Returns    :     	uint8_t
* Description:
* Note:      :
*******************************************************************************/
uint8_t I2C_Read_Reg(uint8_t reg)
{
    uint8_t temp0 = 0;

    I2C_Read_Buffer(reg,&temp0,1);

    return temp0;
}